local name, DB = ...

local frame = CreateFrame"Frame"

frame:SetScript("OnEvent", function (self, event, ...)
	local handler = self[event]
	if handler then handler(self, event, ...) end
end)

frame:RegisterEvent"VARIABLES_LOADED"

--- http://www.wowwiki.com/API_COMBAT_LOG_EVENT
function frame:VARIABLES_LOADED()
	DB.SV = CombatTrackerDB or {
		LineFont = "GameFontHighlightSmall",
		LineTexture = "Interface\\AddOns\\combattracker\\textures\\line",
		LineColor = {0.85, 0.23, 0},
		LineWidth = 250,
		LineHeight = 12,
		MaxLines = 10,
		UpdateFrequency = .5, -- in seconds
		Windows = {
			Self = {
				anchor = { anchor = "TOP", anchorTo = "TOP", offsetX = 120, offsetY = -4 },
				dataset = {
					{"RANGE_DAMAGE","SPELL_DAMAGE","SPELL_PERIODIC_DAMAGE"},
					[[return function (_, _, srcGUID, _, _, _, _, _, _, name, _, amount)
						if srcGUID == $(UnitGUID"player")q then return name, amount end
					end]],
					"SWING_DAMAGE",
					[[return function (_, _, srcGUID, _, _, _, _, _, amount)
						if srcGUID == $(UnitGUID"player")q then return "SWING", amount end
					end]]
				},
			},
			["Group Damage"] = {
				anchor = { anchor = "TOP", anchorTo = "TOP", offsetX = 370, offsetY = -4 },
				dataset = {
					{"RANGE_DAMAGE","SPELL_DAMAGE","SPELL_PERIODIC_DAMAGE"},
					[[local band = bit.band return function (_, _, _, srcName, srcFlags, _, _, _, _, name, _, amount)
						if
							band(srcFlags, $(COMBATLOG_OBJECT_CONTROL_MASK + COMBATLOG_OBJECT_REACTION_MASK)d) == $(COMBATLOG_OBJECT_CONTROL_PLAYER + COMBATLOG_OBJECT_REACTION_FRIENDLY)d
							and band(srcFlags, $(COMBATLOG_OBJECT_AFFILIATION_RAID + COMBATLOG_OBJECT_AFFILIATION_PARTY + COMBATLOG_OBJECT_AFFILIATION_MINE)d) ~= 0
						then return srcName, amount end
					end]],
					"SWING_DAMAGE",
					[[local band = bit.band return function (_, _, _, srcName, srcFlags, _, _, _, amount)
						if
							band(srcFlags, $(COMBATLOG_OBJECT_CONTROL_MASK + COMBATLOG_OBJECT_REACTION_MASK)d) == $(COMBATLOG_OBJECT_CONTROL_PLAYER + COMBATLOG_OBJECT_REACTION_FRIENDLY)d
							and band(srcFlags, $(COMBATLOG_OBJECT_AFFILIATION_RAID + COMBATLOG_OBJECT_AFFILIATION_PARTY + COMBATLOG_OBJECT_AFFILIATION_MINE)d) ~= 0
						then return srcName, amount end
					end]]
				},
				clearOnEnterCombat = true,
			},
		},
	}
	CombatTrackerDB = DB.SV
	DB.LineFont = _G[DB.SV.LineFont]

	self.windows = {}

	self.VARIABLES_LOADED = nil
end

function frame:Register(name, window, dataset)
	window:Attach(dataset)
	if window.SetName then
		window:SetName(name)
	end
	self.windows[name] = window
end

frame:RegisterEvent"PLAYER_REGEN_DISABLED"
function frame:PLAYER_REGEN_DISABLED()
	-- reset datasets
	for _, window in pairs(self.windows) do
		if window.dataset.clearOnEnterCombat and next(window.dataset.identifiers) then
			window.dataset:ClearOnNextAdd()
		end
	end
end

frame:RegisterEvent"PLAYER_REGEN_ENABLED"
function frame:PLAYER_REGEN_ENABLED()
	-- mark dirty datasets
	for _, window in pairs(self.windows) do
		window.dataset:Update(true)
	end
end

local Get_DB_Roster_Name = function (_, id)
	return DB.roster:GetNameByGuid(id)
end

frame:RegisterEvent"PLAYER_LOGIN"
function frame:PLAYER_LOGIN()
	DB.roster:Load(DB.SV)
	DB.roster:Update()
	-- create windows/datasets
	for name, info in pairs(DB.SV.Windows) do
		local w = DB.Window()
		w:SetPoint(info.anchor.anchor, UIParent, info.anchor.anchorTo, info.anchor.offsetX, info.anchor.offsetY)
		w.anchor = info.anchor
		local d = DB.DataSet(unpack(info.dataset))
		if info.guidAsDataSetKey then
			d.GetName = Get_DB_Roster_Name
		end
		d.clearOnEnterCombat = info.clearOnEnterCombat
		self:Register(name, w, d)
		if info.data then
			d:Load(info.data)
		end
	end
end

frame:RegisterEvent"PLAYER_LOGOUT"
function frame:PLAYER_LOGOUT()
	-- save windows/datasets
	for name, window in pairs(self.windows) do
		local info = DB.SV.Windows[name] or {}
		local anchor = window.anchor
		if not anchor then
			local p, _, r, x, y = window:GetPoint(1)
			anchor = {
				anchor = p,
				anchorTo = r,
				offsetX = x,
				offsetY = y,
			}
			info.anchor = anchor
		end
		info.data = {}
		info.clearOnEnterCombat = window.dataset.clearOnEnterCombat
		window.dataset:Save(info.data)
		DB.SV.Windows[name] = info
	end
	DB.roster:Save(DB.SV)
end

DB.core = frame
